home *** CD-ROM | disk | FTP | other *** search
/ Power CD / Power CD ATARI-Rechner Lieben.iso / ACC_CPX / CALC_2 / EXEC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-02-05  |  5.7 KB  |  261 lines

  1. /*
  2.  *    GEM calculator
  3.  *    resource-dependent part: execution
  4.  *    Copyright 1985 Axel T. Schreiner, Ulm, W-Germany
  5.  */
  6.  
  7. #include "b:\calc\calc.h"            /* resource */
  8.  
  9. /*
  10.  *    tunable
  11.  */
  12.  
  13. #define    MAXSTACK    20        /* stack size kludge */
  14.  
  15. typedef    long    number;            /* computational object */
  16.  
  17. #define    MINLEN    6            /* minimum display length */
  18. #define    FMTd    "%c %*ld"        /* decimal output */
  19. #define    FMTx    "%c 0x%0*lx"        /* hexadecimal output */
  20. #define    FMTo    "%c 0%0*lo"        /* octal output */
  21.  
  22. /*
  23.  *    definitions
  24.  */
  25.  
  26. #define    IDLE    0            /* no number started */
  27. #define    NUMBER    1            /* number started */
  28.  
  29. typedef struct stack {            /* value and operator stack */
  30.     struct stack * next;
  31.     number val;            /* must also contain int operator */
  32.     } stack;
  33.  
  34.                     /* need fake dynamic stack, since
  35.                        GEMLIB does not support malloc */
  36. static stack elts[MAXSTACK], *avail, *top = elts;
  37.  
  38. /*
  39.  *    calculator utilities
  40.  */
  41.  
  42. static int pos(op)            /* packed operator index */
  43.     register int op;
  44. {    static int list[] =0{
  45.         BLPAR, BOR, BXOR, BAND, BLSH,
  46.         BRSH, BADD, BSUB, BMULT, BDIV,
  47.         BREM
  48.         };
  49.     register int i;
  50.  
  51.     for (i = 0; list[i] != op; ++ i)
  52.         ;
  53.     return i;            /* assume we find it... */
  54. }
  55.     
  56. static int high(a, b)            /* true if a has priority over b */
  57.     register int a, b;
  58. {    static int prio[] = {        /* operator priority */
  59.         /* BLPAR */        1,
  60.         /* BOR */        2,
  61.         /* BXOR */        3,
  62.         /* BAND */        4,
  63.         /* BLSH, BRSH */    5, 5,
  64.         /* BADD, BSUB */    6, 6,
  65.         /* BMULT, BDIV, BREM */    7, 7, 7
  66.         };
  67.  
  68.     return prio[pos(a)] > prio[pos(b)];
  69. }
  70.  
  71. static number bin(op, a, b)        /* execute binary operator */
  72.     register int op;
  73.     number a, b;
  74. {
  75.     switch (op) {
  76.     case BOR:    return a | b;
  77.     case BXOR:    return a ^ b;
  78.     case BAND:    return a & b;
  79.     case BLSH:    return a << b;
  80.     case BRSH:    return a >> b;
  81.     case BADD:    return a + b;
  82.     case BSUB:    return a - b;
  83.     case BMULT:    return a * b;
  84.     case BDIV:    return b? a / b: 0;
  85.     case BREM:    return b? a % b: 0;
  86.     }
  87. }
  88.  
  89. static stack * push(next, val)
  90.     register stack * next;        /* onto this stack */
  91.     number val;            /* this value */
  92. {    register stack * p;
  93.  
  94.     if (avail)            /* recycle */
  95.         p = avail, avail = avail->next;
  96.     else if (top)            /* use new element */
  97.     {    p = top;
  98.         if (++ top >= elts + MAXSTACK)
  99.             top = (stack *) 0;
  100.     }
  101.     else                /* sorry, Charlie... */
  102.     {    Alert(ASTACK);
  103.         return (stack *) 0;
  104.     }
  105.     p->next = next;
  106.     p->val = val;
  107.     return p;
  108. }
  109.  
  110. static free(p)
  111.     stack * p;
  112. {
  113.     p->next = avail, avail = p;
  114. }
  115.  
  116. /*
  117.  *    calculator
  118.  */
  119.  
  120. int Calc(code, bp, l)            /* true if we should quit */
  121.     register int code;        /* digit or operation */
  122.     char * bp;            /* first call: output buffer */
  123.     int l;                /* first call: text length */
  124. {    static stack * opr,        /* operator stack */
  125.         * ond;            /* operand stack */
  126.     static int state = IDLE,    /* of automaton */
  127.         sign = 1,        /* extra sign of display */
  128.         base = 10,        /* base for display */
  129.         lpar = 0;        /* open ( */
  130.     static number display = 0,    /* assembled number */
  131.         value = 0;        /* sign included */
  132.     static char * buf;        /* display buffer */
  133.     static int len;
  134.  
  135.     register stack * p;
  136.  
  137.     if (! buf)            /* first call */
  138.         if ((len = l) < MINLEN)
  139.         {    Alert(ASMALL);
  140.             return 1;
  141.         }
  142.         else
  143.             buf = bp;
  144.  
  145.     switch (code) {
  146.     case BZERO:    code = 0;  goto digit;
  147.     case BONE:    code = 1;  goto digit;
  148.     case BTWO:    code = 2;  goto digit;
  149.     case BTHREE:    code = 3;  goto digit;
  150.     case BFOUR:    code = 4;  goto digit;
  151.     case BFIVE:    code = 5;  goto digit;
  152.     case BSIX:    code = 6;  goto digit;
  153.     case BSEVEN:    code = 7;  goto digit;
  154.     case BEIGHT:    code = 8;  goto digit;
  155.     case BNINE:    code = 9;  goto digit;
  156.     case BA:    code = 10;  goto digit;
  157.     case BB:    code = 11;  goto digit;
  158.     case BC:    code = 12;  goto digit;
  159.     case BD:    code = 13;  goto digit;
  160.     case BE:    code = 14;  goto digit;
  161.     case BF:    code = 15;
  162.     digit:
  163.         if (state == IDLE)
  164.             display = 0, state = NUMBER;
  165.         display = display * base + code;
  166.         value = sign*display;
  167.         break;
  168.     case BMINUS:
  169.         sign = - sign;
  170.         value = sign*display;
  171.         break;
  172.     case BCOMP:            /* hmmmm... */
  173.         display = ~display;
  174.         value = sign*display;
  175.         break;
  176.     case BDEC:
  177.         base = 10;
  178.         break;
  179.     case BOCT:
  180.         base = 8;
  181.         break;
  182.     case BHEX:
  183.         base = 16;
  184.         break;
  185.     case BEQUAL:
  186.         while (opr)
  187.         {    if (opr->val != BLPAR)
  188.             {    value = bin((int) opr->val, ond->val, value);
  189.                 p = ond->next, free(ond), ond = p;
  190.             }
  191.             p = opr->next, free(opr), opr = p;
  192.         }
  193.         display = value, sign = 1, state = IDLE;
  194.         break;
  195.     case BOR:
  196.     case BXOR:
  197.     case BAND:
  198.     case BLSH:
  199.     case BRSH:
  200.     case BADD:
  201.     case BSUB:
  202.     case BMULT:
  203.     case BDIV:
  204.     case BREM:
  205.         while (opr && ! high(code, (int) opr->val))
  206.         {    value = bin((int) opr->val, ond->val, value);
  207.             p = ond->next, free(ond), ond = p;
  208.             p = opr->next, free(opr), opr = p;
  209.         }
  210.         if (! (p = push(opr, (number) code)))
  211.             goto clear;
  212.         opr = p;
  213.         if (! (p = push(ond, value)))
  214.             goto clear;
  215.         ond = p;
  216.         display = value, sign = 1, state = IDLE;
  217.         break;
  218.     case BLPAR:
  219.         if (state == IDLE)
  220.         {    ++ lpar;
  221.             if (! (p= push(opr, (number) code)))
  222.                 goto clear;
  223.             opr = p;
  224.         }
  225.         else
  226.             Alert(APAREN);
  227.         return 0;
  228.     case BRPAR:
  229.         if (state == IDLE || ! lpar)
  230.         {    Alert(APAREN);
  231.             return 0;
  232.         }
  233.         while (opr && opr->val != BLPAR)
  234.         {    value = bin((int) opr->val, ond->val, value);
  235.             p = ond->next, free(ond), ond = p;
  236.             p = opr->next, free(opr), opr = p;
  237.         }
  238.         --lpar, p = opr->next, free(opr), opr = p;
  239.         display = value, sign = 1, state = IDLE;
  240.         break;
  241.     case BCLEAR:
  242.     clear:
  243.         while (opr)
  244.             p = opr->next, free(opr), opr = p;
  245.         while (ond)
  246.             p = ond->next, free(ond), ond = p;
  247.         lpar = 0;
  248.         base = 10;
  249.     case BCENTRY:
  250.         display = value = 0;
  251.         sign = 1;
  252.         state = IDLE;
  253.     }
  254.     sprintf(buf,
  255.         base == 8? FMTo: base == 16? FMTx: FMTd,
  256.         value < 0? '-': ' ',
  257.         base == 8? len-4: base == 16? len-5: len-3,
  258.         value < 0? -value: value);
  259.     return 0;
  260. }
  261. ə